# 本文件实现网页的解析与信息注入工作
import pyperclip
import time
import random
import pyautogui

from typing import Dict, List, Tuple
from selenium import webdriver
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from pynput.keyboard import Controller, Key


def random_sleep(t: float = 0.0):
    """
    随机等待 t 秒到 t+1 秒。

    参数:
    t (float): 最小等待时间
    """
    time.sleep(t + random.random())


def select_bind_button(driver: WebDriver, button_name: str = "全部"):
    """
    根据输入的按钮名称 点击是否绑定wegame/taptap相应的按钮。

    参数:
    driver: Selenium WebDriver对象
    button_name (str): 可选值为 "全部", "是", "否"
    """
    allowed_buttons = ["全部", "是", "否"]
    if button_name not in allowed_buttons:
        raise ValueError(f"Bind WeGame/TapTap: 无效的按钮名称={button_name}")

    button = driver.find_element(By.XPATH, f"//div[text()='{button_name}']")
    button.click()  # 点击找到的按钮
    print(f"Bind WeGame/TapTap: 成功点击 '{button_name}' 按钮.")


def select_system_button(driver: WebDriver, button_name: str = "官服"):
    """
    根据输入的系统名称 点击相应的系统按钮。

    参数:
    driver: Selenium WebDriver对象
    button_name (str): 可选值为 "官服", "哔哩哔哩", "UID靓号", "小米服", "华为服", "OPPO服", "魅族服", "国际服"
    """
    # 允许的按钮名称
    allowed_buttons = [
        "官服",
        "哔哩哔哩",
        "UID靓号",
        "小米服",
        "华为服",
        "OPPO服",
        "魅族服",
        "国际服",
    ]

    # 检查按钮名称是否有效
    if button_name not in allowed_buttons:
        raise ValueError(f"Select System Button: 无效的按钮名称={button_name}")

    # 根据按钮名称选择相应的按钮并点击
    button = driver.find_element(By.XPATH, f"//div[text()='{button_name}']")
    button.click()  # 点击找到的按钮

    # 输出点击结果
    print(f"Select System Button: 成功点击 '{button_name}' 按钮.")


def select_gender_button(driver: WebDriver, button_name: str = "全部"):
    """
    根据输入的性别或全部选择按钮点击相应的按钮。

    参数:
    driver: Selenium WebDriver对象
    button_name (str): 可选值为 "全部", "男主", "女主"
    """
    # 允许的按钮名称
    allowed_buttons = ["全部", "男主", "女主"]

    # 检查按钮名称是否有效
    if button_name not in allowed_buttons:
        raise ValueError(f"性别设置错误: 无效的按钮名称={button_name}")

    button = driver.find_element(By.XPATH, f"//div[text()='{button_name}']")
    button.click()  # 点击找到的按钮

    # 输出点击结果
    print(f"已设置性别选项: 成功点击 '{button_name}' 按钮.")


def select_account_type_checkbox(driver: WebDriver, account_type: str = ""):
    """

    点击允许的复选框。如果传入具体的account_type，则仅点击该复选框。
    driver: Selenium WebDriver对象
    account_type: 指定的复选框名称。如果为空字符串，则不进行勾选。
    """
    # 允许的复选框名称
    allowed_checkboxes = ["初始号", "顶级账号", "诚心卖"]

    # 如果传入了具体的account_type，则仅点击该复选框
    if account_type != "":
        if account_type in allowed_checkboxes:
            checkboxes = driver.find_elements(By.CSS_SELECTOR, "div.group")
            for checkbox in checkboxes:
                checkbox_text = checkbox.text.strip()
                if checkbox_text == account_type:
                    checkbox.click()
                    print(f"点击了复选框: {checkbox_text}")
        else:
            print(f"复选框名称 '{account_type}' 不在允许的范围内。")
    else:
        print("未指定账号类型, 已跳过勾选。")


def set_price(driver: WebDriver, low: int, high: int):
    """
    driver: Selenium WebDriver对象
    模拟输入价格区间。要求 low 和 high 为合法整数且 low <= high。
    low: 价格下限
    high: 价格上限
    """
    # 检查输入参数的合法性
    if not isinstance(low, int) or not isinstance(high, int):
        raise ValueError("价格下限和上限必须是整数。")

    if low > high:
        raise ValueError("价格下限不能大于上限。")

    # 定位到下限输入框并输入价格
    low_input = driver.find_element(By.CSS_SELECTOR, "input[placeholder='下限']")
    low_input.clear()  # 清空已有内容
    low_input.send_keys(str(low))  # 输入下限价格

    # 定位到上限输入框并输入价格
    high_input = driver.find_element(By.CSS_SELECTOR, "input[placeholder='上限']")
    high_input.clear()  # 清空已有内容
    high_input.send_keys(str(high))  # 输入上限价格

    print(f"已设置价格区间：下限 = {low}, 上限 = {high}")


def set_weapon(weapon_dict: Dict, weapon_box_coordinate: Tuple[int, int]):
    """用pyautogui模拟用户选择的武器

    Args:
        weapon_dict (Dict): 武器与对应坐标
    """
    # 点击武器选择框
    pyautogui.moveTo(weapon_box_coordinate[0], weapon_box_coordinate[1])
    pyautogui.click()
    random_sleep()
    # 选择需要的武器
    for weapon, coordinate in weapon_dict.items():
        pyautogui.moveTo(coordinate[0], coordinate[1])
        pyautogui.click()
        random_sleep()


def simulate_input(your_str: str):
    """利用pyperclip模拟用户输入
        将传入字符串保存到剪贴板 模拟Ctrl+C和Ctrl+V
    Args:
        your_str (str): 需要输入的字符串
    """
    # 保存输入到字符串
    pyperclip.copy(your_str)

    keyboard = Controller()
    # 模拟 Ctrl+V 粘贴
    keyboard.press(Key.ctrl)
    keyboard.press("v")
    keyboard.release("v")
    keyboard.release(Key.ctrl)
    time.sleep(0.1)  # 等待粘贴操作完成


def set_character_chain2(
    character_name: str,
    character_box_coordinate: Tuple[int, int],
    chain2_coordinate: Tuple[int, int],
):
    """用pyautogui模拟用户选择的武器

    Args:
        character_name (str): 角色名称
        character_box_coordinate (Tuple[int, int]): 角色选择框坐标
        chain2_coordinate (Tuple[int, int]): 2命选择框坐标
    """
    # 点击角色选择框
    pyautogui.moveTo(character_box_coordinate[0], character_box_coordinate[1])
    pyautogui.click()
    random_sleep()

    # 输入需要的角色
    simulate_input("椿")
    random_sleep()

    # 点击2命选择框
    pyautogui.moveTo(chain2_coordinate[0], chain2_coordinate[1])
    random_sleep()
    pyautogui.click()
    random_sleep()


def click_your_coordinate(coordinate: Tuple[int, int]):
    """用pyautogui模拟用户点击传入的坐标

    Args:
        coordinate (Tuple[int, int]): 坐标
    """
    pyautogui.moveTo(coordinate[0], coordinate[1])
    pyautogui.click()
    random_sleep()


def extract_account_info(driver: WebDriver) -> list:
    """
    使用 Selenium 抓取页面中指定的账户信息，返回一个 list。

    Args:
        driver (WebDriver): Selenium WebDriver 对象。

    Returns:
        list: 包含所有账户信息的列表。
    """
    try:
        # 定位包含账户信息的所有元素
        account_info_elements = driver.find_elements(
            By.XPATH,
            '//div[contains(@class, "line-clamp-2") and contains(@class, "text-Medium")]',
        )

        # 提取每个元素的文本信息
        account_info_list = [element.text for element in account_info_elements]

        return account_info_list
    except Exception as e:
        print(f"抓取账户信息时出现错误: {e}")
        return []


def extract_account_price(driver: WebDriver) -> list:
    """
    使用 Selenium 抓取页面中账号价格信息，返回一个 list。

    Args:
        driver (WebDriver): Selenium WebDriver 对象。

    Returns:
        list: 包含所有账号价格的列表。
    """
    try:
        # 定位包含价格信息的所有元素
        price_elements = driver.find_elements(
            By.XPATH,
            '//div[contains(@class, "text-rubik-semi-bold") and contains(@text, "#FF543C")]',
        )

        # 提取每个元素的文本信息并转换为整数
        price_list = [int(element.text.strip()) for element in price_elements]

        return price_list
    except Exception as e:
        print(f"抓取价格信息时出现错误: {e}")
        return []

